package org.springcloud.plugin.config.center.nacos.adapter;


import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.listener.Event;
import com.alibaba.nacos.api.naming.listener.EventListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springcloud.plugin.common.entity.RuleEntity;
import org.springcloud.plugin.common.nacos.operation.NacosOperation;
import org.springcloud.plugin.common.nacos.operation.NacosSubscribeCallback;
import org.springcloud.plugin.common.thread.NamedThreadFactory;
import org.springcloud.plugin.config.center.adpater.AbstractConfigAdapter;
import org.springcloud.plugin.config.center.parser.CoreConfigParser;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author yanggld
 * @Date 2019/12/12-17:21
 * @Description
 */
@Slf4j
public class NacosConfigAdapter extends AbstractConfigAdapter {
	/**
	 * com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource
	 */
	private final ExecutorService executorService = new ThreadPoolExecutor(2, 4, 0, TimeUnit.MILLISECONDS,
			new ArrayBlockingQueue<Runnable>(1), new NamedThreadFactory("nacos-config"),
			new ThreadPoolExecutor.DiscardOldestPolicy());

	@Autowired
	private NacosOperation nacosOperation;

	@Autowired
	private CoreConfigParser coreConfigParser;

	private Listener partialListener;
	private Listener globalListener;

	/**
	 * 服务启动时获取配置
	 * @return
	 * @throws Exception
	 * 先获取单独配置，如果没有单独配置则获取全局及配置
	 */
	@Override
	public String getConfig() throws Exception {
		String config = getConfig(false);
		if (StringUtils.isNotEmpty(config)) {
			log.info("************获取单独配置数据********");
			return config;
		} else {
			log.info("************未找到单独配置数据********");
		}
		config = getConfig(true);
		if (StringUtils.isNotEmpty(config)) {
			log.info("************获取全局配置数据********");
			return config;
		} else {
			log.info("************未找到全局配置数据********");
		}
		return config;
	}

	/**
	 * 从配置中心获取配置
	 * @param globalConfig 是否全局配置
	 * @return
	 * @throws Exception
	 * 全局配置时：dataId=group
	 * 单独配置时: dataId=serviceId
	 */
	private String getConfig(boolean globalConfig) throws Exception {
		String serviceId = coreAdapter.getServiceId();
		String group = coreAdapter.getGroup();
		String content = nacosOperation.getConfig( group, globalConfig ? group : serviceId,3000);
		return content;
	}

	/**
	 * 服务启动之后监听配置的修改
	 */
	@PostConstruct
	public void subscribeConfig() {
		partialListener = subscribeConfig(false);
		globalListener = subscribeConfig(true);
		subscribeService();
	}

	/**
	 * 监听服务
	 */
	private EventListener subscribeService() {
		String serviceId = coreAdapter.getServiceId();
		String group = coreAdapter.getGroup();
		try {
			return nacosOperation.subscribeService(serviceId,new NacosSubscribeCallback() {
				@Override
				public void callback(String config) {
				}
				@Override
				public void callback(Event event) {
					log.info("监听服务的变化~~~~~~~~~~~~~~~~~~~~~");
				}
			});
		} catch (NacosException e) {
			log.error(e.getMessage());
		}
		return null;
	}


	/**
	 * 监听nacos配置的的修改
	 * @param globalConfig
	 * @return
	 */
	private Listener subscribeConfig(boolean globalConfig) {
		String serviceId = coreAdapter.getServiceId();
		String group = coreAdapter.getGroup();
		try {
			return nacosOperation.subscribeConfig(group, globalConfig ? group : serviceId, executorService, new NacosSubscribeCallback() {
				@Override
				public void callback(String config) {
					log.info("***********监听配置已修改****************：");
					log.info(config);
					RuleEntity ruleEntity = coreConfigParser.parse(config);
					coreAdapter.setRule(ruleEntity);
				}
				@Override
				public void callback(Event event) {
				}
			});
		} catch (Exception e) {
			log.error(e.getMessage());
		}
		return null;
	}

}
